/***********************************************************************************
 * 文件名： HC32_FunctionDefine.h
 * 作者： 刘言
 * 版本： 2
 * 说明：
 *      自定义的外设操作库，官方提供的库函数操作效率低、占用高，这里定义的都是直接操作寄存器
 *  的宏。这种方式可以同样用于STM32等Cortex-M系列内核MCU。
 *      hc32xxxx.h 中已经定义好了寄存器，且使用位偏移结构体定义好了位访问。
 * 修改记录：
 *      2020/6/22: 初版。 刘言。
 *      2020/8/18: 增加多MCU型号系列的支持，新增HC32L13X系列的支持。
***********************************************************************************/
#ifndef _HC32_FUNCTION_DEFINE_H_
#define _HC32_FUNCTION_DEFINE_H_

#ifdef __cplusplus
 extern "C" {
#endif

// NVIC 和 SysTick 属于Cortex内核外设，CMSIS中已经包含了其操作API，源代码见 core_cm0plus.h

// NVIC默认中断优先级为0（最高优先级，3为最低优先级）

/////////////////////////////// SYSCTRL 的操作宏，主要用于时钟控制 ///////////////////////////////////////////

// 解锁 SYSCTRL0 和 SYSCTRL1 寄存器，写入一次后自动上锁
#define _SYSCTRL_UNLOCK  {M0P_SYSCTRL->SYSCTRL2 = 0x5A5A; M0P_SYSCTRL->SYSCTRL2 = 0xA5A5;}


// 设置RCL目标频率为32768HZ，注意不代表使能了RCL
#define SYSCTRL_SET_RCL_32768HZ       M0P_SYSCTRL->RCL_CR = *((volatile uint16_t *)0x00100C22ul)

// 设置RCL目标频率为38400HZ，注意不代表使能了RCL
#define SYSCTRL_SET_RCL_38400HZ       M0P_SYSCTRL->RCL_CR = *((volatile uint16_t *)0x00100C20ul)

// 使能RCL并等待其稳定
#define SYSCTRL_ENABLE_RCL          {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL0_f.RCL_EN = 1;while(1 != M0P_SYSCTRL->RCL_CR_f.STABLE);}

// 关闭RCL 可以降低功耗
#define SYSCTRL_DISABLE_RCL         {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL0_f.RCL_EN = 0;}

// 切换系统时钟源为RCL，在此之前确保已经使能了RCL。
#define SYSCTRL_SWITCH_SYSCLK_TO_RCL       {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL0_f.CLKSW = 2;}


// 设置RCH目标频率为24MHZ，注意不代表使能了RCH
#define SYSCTRL_SET_RCH_24MHZ       M0P_SYSCTRL->RCH_CR = *((volatile uint16_t *)0x00100C00ul)

// 设置RCH目标频率为22.12MHZ，注意不代表使能了RCH
#define SYSCTRL_SET_RCH_22_12MHZ       M0P_SYSCTRL->RCH_CR = *((volatile uint16_t *)0x00100C02ul)

// 设置RCH目标频率为16MHZ，注意不代表使能了RCH
#define SYSCTRL_SET_RCH_16MHZ       M0P_SYSCTRL->RCH_CR = *((volatile uint16_t *)0x00100C04ul)

// 设置RCH目标频率为8MHZ，注意不代表使能了RCH
#define SYSCTRL_SET_RCH_8MHZ       M0P_SYSCTRL->RCH_CR = *((volatile uint16_t *)0x00100C06ul)

// 设置RCH目标频率为4MHZ，注意不代表使能了RCH
#define SYSCTRL_SET_RCH_4MHZ       M0P_SYSCTRL->RCH_CR = *((volatile uint16_t *)0x00100C08ul)

// 使能RCH并等待其稳定
#define SYSCTRL_ENABLE_RCH          {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL0_f.RCH_EN = 1; while(1 != M0P_SYSCTRL->RCH_CR_f.STABLE);}

// 关闭RCH 可以降低功耗
#define SYSCTRL_DISABLE_RCH         {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL0_f.RCH_EN = 0;}

// 切换系统时钟源为RCH，在此之前确保已经使能了RCH。
#define SYSCTRL_SWITCH_SYSCLK_TO_RCH       {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL0_f.CLKSW = 0;}

// 切换SWD端口为普通IO，SWD将无法使用。（上电默认为SWD端口）
#define SYSCTRL_SWD_USE_IO              {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL1_f.SWD_USE_IO = 1;}

// 切换SWD端口为SWD功能
#define SYSCTRL_SWD_USE_SWD             {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL1_f.SWD_USE_IO = 0;}

// 切换RESET端口为普通IO。（上电默认为RESET端口）
#define SYSCTRL_RESET_USE_IO            {_SYSCTRL_UNLOCK; M0P_SYSCTRL->SYSCTRL1_f.RES_UIO = 1;}

// SYSCTRL PERI_CLKEN寄存器各个外设时钟使能位掩码

#define ALL_CLKEN               0XFFFFFFFF
#define FLASH_CLKEN             (1<<31)
#define DIV_CLKEN               (1<<30)
#define DMA_CLKEN               (1<<29)
#define GPIO_CLKEN              (1<<28)
#define AES_CLKEN               (1<<27)
#define CRC_CLKEN               (1<<26)
#define SWD_CLKEN               (1<<25)
#define SYSTICK_CLKEN           (1<<24)
#define LCD_CLKEN               (1<<22)
#define CLKTRIM_CLKEN           (1<<21)
#define RTC_CLKEN               (1<<20)
#define PCNT_CLKEN              (1<<19)
#define RNG_CLKEN               (1<<18)
#define VCLVD_CLKEN             (1<<17)
#define ADC_CLKEN               (1<<16)
#define WDT_CLKEN               (1<<15)
#define PCA_CLKEN               (1<<14)
#define OPA_CLKEN               (1<<13)
#define TIM3_CLKEN              (1<<11)
#define ADTIM_CLKEN             (1<<10)
#define LPTIM_CLKEN             (1<<9)     
#define BASETIM_CLKEN           (1<<8)
#define GENTIM_CLKEN            (1<<8)
#define SPI1_CLKEN              (1<<7)
#define SPI_CLKEN               (1<<6)
#define SPI0_CLKEN              (1<<6)
#define I2C1_CLKEN              (1<<5)
#define I2C_CLKEN               (1<<4)
#define I2C0_CLKEN              (1<<4)
#define LPUART1_CLKEN           (1<<3)
#define LPUART0_CLKEN           (1<<2)
#define UART1_CLKEN             (1<<1)
#define UART0_CLKEN             (1<<0)

// 使能所有外设时钟
#define SYSCTRL_ENABLE_ALL_CLK      M0P_SYSCTRL->PERI_CLKEN = 0XFFFFFFFF
// 使能 GPIO 外设时钟门控
#define SYSCTRL_ENABLE_GPIO_CLK     M0P_SYSCTRL->PERI_CLKEN_f.GPIO=1

#define SYSCTRL_ENABLE_ADC_CLK      M0P_SYSCTRL->PERI_CLKEN_f.ADC=1

#define SYSCTRL_ENABLE_BASETIM_CLK  M0P_SYSCTRL->PERI_CLKEN_f.BASETIM = 1

#define SYSCTRL_ENABLE_UART0_CLK    M0P_SYSCTRL->PERI_CLKEN_f.UART0 = 1

#define SYSCTRL_ENABLE_UART1_CLK    M0P_SYSCTRL->PERI_CLKEN_f.UART1 = 1

/*待补充*/


#if (HC32_MCU_SERIES == HC32F005)
        #include "HC32F005_FunDef.h"
#elif (HC32_MCU_SERIES == HC32L13X)
        #include "HC32L13X_FunDef.h"
#endif


/////////////////////////////// GPIO 的操作宏 ///////////////////////////////////////////

// 输入模式（默认）
#define GPIO_DIR_INPUT(port, pin)    *((volatile uint32_t *)(M0P_GPIO_BASE + 0x100 + port * 0x40)) |= (1<<pin)
// 输出模式
#define GPIO_DIR_OUTPUT(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x100 + port * 0x40)) &= ~(1<<pin)

// 设置为模拟端口
#define GPIO_ADS_ANALOG(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x10C + port * 0x40)) |= (1<<pin)
// 设置为数字端口（默认）
#define GPIO_ADS_DIGIT(port, pin)    *((volatile uint32_t *)(M0P_GPIO_BASE + 0x10C + port * 0x40)) &= ~(1<<pin)

// 开启上拉电阻
#define GPIO_PU_ENABLE(port, pin)    *((volatile uint32_t *)(M0P_GPIO_BASE + 0x120 + port * 0x40)) |= (1<<pin)
// 关闭上拉电阻（默认）
#define GPIO_PU_DISABLE(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x120 + port * 0x40)) &= ~(1<<pin)

// 开启下拉电阻
#define GPIO_PD_ENABLE(port, pin)    *((volatile uint32_t *)(M0P_GPIO_BASE + 0x124 + port * 0x40)) |= (1<<pin)
// 关闭下拉电阻（默认）
#define GPIO_PD_DISABLE(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x124 + port * 0x40)) &= ~(1<<pin)

// 设置为开漏（输出）
#define GPIO_OD_ENABLE(port, pin)    *((volatile uint32_t *)(M0P_GPIO_BASE + 0x12C + port * 0x40)) |= (1<<pin)
// 设置为推挽（输出）(默认)
#define GPIO_OD_DISABLE(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x12C + port * 0x40)) &= ~(1<<pin)

// 使能高电平中断
#define GPIO_HIE_ENABLE(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x130 + port * 0x40)) |= (1<<pin)
// 禁止高电平中断（默认）
#define GPIO_HIE_DISABLE(port, pin)  *((volatile uint32_t *)(M0P_GPIO_BASE + 0x130 + port * 0x40)) &= ~(1<<pin)

// 使能低电平中断
#define GPIO_LIE_ENABLE(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x134 + port * 0x40)) |= (1<<pin)
// 禁止低电平中断（默认）
#define GPIO_LIE_DISABLE(port, pin)  *((volatile uint32_t *)(M0P_GPIO_BASE + 0x134 + port * 0x40)) &= ~(1<<pin)

// 使能上升沿中断
#define GPIO_RIE_ENABLE(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x138 + port * 0x40)) |= (1<<pin)
// 禁止上升沿中断（默认）
#define GPIO_RIE_DISABLE(port, pin)  *((volatile uint32_t *)(M0P_GPIO_BASE + 0x138 + port * 0x40)) &= ~(1<<pin)

// 使能下降沿中断
#define GPIO_FIE_ENABLE(port, pin)   *((volatile uint32_t *)(M0P_GPIO_BASE + 0x13C + port * 0x40)) |= (1<<pin)
// 禁止下降沿中断（默认）
#define GPIO_FIE_DISABLE(port, pin)  *((volatile uint32_t *)(M0P_GPIO_BASE + 0x13C + port * 0x40)) &= ~(1<<pin)






                            




#ifdef __cplusplus
 }
#endif

#endif